diff --git a/web/modals/threads/notifications/enum-settings-option-info.css b/web/components/enum-settings-option-info.css similarity index 100% rename from web/modals/threads/notifications/enum-settings-option-info.css rename to web/components/enum-settings-option-info.css diff --git a/web/modals/threads/notifications/enum-settings-option-info.react.js b/web/components/enum-settings-option-info.react.js similarity index 92% rename from web/modals/threads/notifications/enum-settings-option-info.react.js rename to web/components/enum-settings-option-info.react.js index eb8ef4383..dbcb88474 100644 --- a/web/modals/threads/notifications/enum-settings-option-info.react.js +++ b/web/components/enum-settings-option-info.react.js @@ -1,37 +1,37 @@ // @flow import classnames from 'classnames'; import * as React from 'react'; -import SWMansionIcon from '../../../SWMansionIcon.react'; +import SWMansionIcon from '../SWMansionIcon.react'; import css from './enum-settings-option-info.css'; type Props = { +valid: boolean, +children: React.Node, }; function EnumSettingsOptionInfo(props: Props): React.Node { const { valid, children } = props; const optionInfoClasses = React.useMemo( () => classnames(css.optionInfo, { [css.optionInfoInvalid]: !valid, }), [valid], ); const icon = React.useMemo( () => , [valid], ); return (
{icon} {children}
); } export default EnumSettingsOptionInfo; diff --git a/web/modals/threads/notifications/enum-settings-option.css b/web/components/enum-settings-option.css similarity index 100% rename from web/modals/threads/notifications/enum-settings-option.css rename to web/components/enum-settings-option.css diff --git a/web/modals/threads/notifications/enum-settings-option.react.js b/web/components/enum-settings-option.react.js similarity index 95% rename from web/modals/threads/notifications/enum-settings-option.react.js rename to web/components/enum-settings-option.react.js index 9a8305b4d..1cc865ef3 100644 --- a/web/modals/threads/notifications/enum-settings-option.react.js +++ b/web/components/enum-settings-option.react.js @@ -1,53 +1,53 @@ // @flow import classnames from 'classnames'; import * as React from 'react'; -import Radio from '../../../components/radio.react'; -import EnumSettingsOptionInfo from './enum-settings-option-info.react'; +import EnumSettingsOptionInfo from './enum-settings-option-info.react.js'; import css from './enum-settings-option.css'; +import Radio from './radio.react'; type Props = { +selected: boolean, +onSelect: () => void, +icon: React.Node, +title: string, +statements: $ReadOnlyArray<{ +statement: string, +isStatementValid: boolean, }>, }; function EnumSettingsOption(props: Props): React.Node { const { icon, title, statements, selected, onSelect } = props; const descriptionItems = React.useMemo( () => statements.map(({ statement, isStatementValid }) => ( {statement} )), [statements], ); const optionContainerClasses = React.useMemo( () => classnames(css.optionContainer, { [css.optionContainerSelected]: selected, }), [selected], ); return (
{icon}
{title}
{descriptionItems}
); } export default EnumSettingsOption; diff --git a/web/modals/threads/notifications/notifications-modal.react.js b/web/modals/threads/notifications/notifications-modal.react.js index 6641778ef..e90e7a48b 100644 --- a/web/modals/threads/notifications/notifications-modal.react.js +++ b/web/modals/threads/notifications/notifications-modal.react.js @@ -1,192 +1,192 @@ // @flow import * as React from 'react'; import { updateSubscription, updateSubscriptionActionTypes, } from 'lib/actions/user-actions'; import { threadInfoSelector } from 'lib/selectors/thread-selectors'; import { useServerCall, useDispatchActionPromise, } from 'lib/utils/action-utils'; import { assetCacheURLPrefix, backgroundNotificationsIllustrationFileName, backgroundNotificationsIllustrationHeight, backgroundNotificationsIllustrationWidth, badgeOnlyNotificationsIllustrationFileName, badgeOnlyNotificationsIllustrationHeight, badgeOnlyNotificationsIllustrationWidth, focusedNotificationsIllustrationFileName, focusedNotificationsIllustrationHeight, focusedNotificationsIllustrationWidth, } from '../../../assets.js'; import Button from '../../../components/button.react'; +import EnumSettingsOption from '../../../components/enum-settings-option.react'; import { useSelector } from '../../../redux/redux-utils'; import Modal from '../../modal.react'; -import EnumSettingsOption from './enum-settings-option.react'; import css from './notifications-modal.css'; type NotificationSettings = 'focused' | 'badge-only' | 'background'; type Props = { +threadID: string, +onClose: () => void, }; function NotificationsModal(props: Props): React.Node { const { onClose, threadID } = props; const threadInfo = useSelector(state => threadInfoSelector(state)[threadID]); const { subscription } = threadInfo.currentUser; const initialThreadSetting = React.useMemo(() => { if (!subscription.home) { return 'background'; } if (!subscription.pushNotifs) { return 'badge-only'; } return 'focused'; }, [subscription.home, subscription.pushNotifs]); const [ notificationSettings, setNotificationSettings, ] = React.useState(initialThreadSetting); const onFocusedSelected = React.useCallback( () => setNotificationSettings('focused'), [], ); const onBadgeOnlySelected = React.useCallback( () => setNotificationSettings('badge-only'), [], ); const onBackgroundSelected = React.useCallback( () => setNotificationSettings('background'), [], ); const isFocusedSelected = notificationSettings === 'focused'; const focusedItem = React.useMemo(() => { const statements = [ { statement: 'Banner notifs', isStatementValid: true }, { statement: 'Badge count', isStatementValid: true }, { statement: 'Lives in Focused tab', isStatementValid: true }, ]; const icon = ( ); return ( ); }, [isFocusedSelected, onFocusedSelected]); const isFocusedBadgeOnlySelected = notificationSettings === 'badge-only'; const focusedBadgeOnlyItem = React.useMemo(() => { const statements = [ { statement: 'Banner notifs', isStatementValid: false }, { statement: 'Badge count', isStatementValid: true }, { statement: 'Lives in Focused tab', isStatementValid: true }, ]; const icon = ( ); return ( ); }, [isFocusedBadgeOnlySelected, onBadgeOnlySelected]); const isBackgroundSelected = notificationSettings === 'background'; const backgroundItem = React.useMemo(() => { const statements = [ { statement: 'Banner notifs', isStatementValid: false }, { statement: 'Badge count', isStatementValid: false }, { statement: 'Lives in Background tab', isStatementValid: true }, ]; const icon = ( ); return ( ); }, [isBackgroundSelected, onBackgroundSelected]); const dispatchActionPromise = useDispatchActionPromise(); const callUpdateSubscription = useServerCall(updateSubscription); const onClickSave = React.useCallback(() => { dispatchActionPromise( updateSubscriptionActionTypes, callUpdateSubscription({ threadID: threadID, updatedFields: { home: notificationSettings !== 'background', pushNotifs: notificationSettings === 'focused', }, }), ); onClose(); }, [ callUpdateSubscription, dispatchActionPromise, notificationSettings, onClose, threadID, ]); return (
{focusedItem} {focusedBadgeOnlyItem} {backgroundItem}
); } export default NotificationsModal;